'use strict';

/**
 * 角色服务
 */
const Service = require('egg').Service;
const { generateSnowflakeId } = require('../utils/snowflake');

class RoleService extends Service {
  /**
   * 创建角色
   * @param {Object} roleData - 角色数据
   * @return {Promise<Object>} 创建的角色
   */
  async create(roleData) {
    const { ctx } = this;

    // 检查code是否已存在
    if (roleData.code) {
      const existingRole = await ctx.model.Role.findOne({
        where: { code: roleData.code }
      });
      if (existingRole) {
        ctx.throw(400, '角色编码已存在，请使用其他编码');
      }
    }

    // 如果status字段没有传值，则默认为1
    if (!roleData.status) {
      roleData.status = 1;
    }
    return ctx.model.Role.create(roleData);
  }

  /**
   * 查询角色列表
   * @param {Object} query - 查询条件
   * @param {Number} page - 页码
   * @param {Number} pageSize - 每页数量
   * @return {Promise<Object>} 角色列表和总数
   */
  async list(query = {}, page = 1, pageSize = 10) {
    const { ctx } = this;
    const offset = (page - 1) * pageSize;
    const where = {};

    if (query.name) {
      where.name = { [ctx.app.Sequelize.Op.like]: `%${query.name}%` };
    }

    if (query.code) {
      where.code = { [ctx.app.Sequelize.Op.like]: `%${query.code}%` };
    }

    if (query.status !== undefined && query.status !== '') {
      where.status = query.status;
    }

    const { count, rows } = await ctx.model.Role.findAndCountAll({
      where,
      offset,
      limit: pageSize,
      order: [['create_time', 'DESC']],
    });

    return {
      list: rows,
      total: count,
      page,
      pageSize,
    };
  }

  /**
   * 查询单个角色
   * @param {string} id - 角色ID
   * @return {Promise<Object>} 角色信息
   */
  async findById(id) {
    const { ctx } = this;
    return ctx.model.Role.findByPk(id, {
      include: [
        { model: ctx.model.User, as: 'users', attributes: ['id', 'username', 'realName'], through: { attributes: [] } },
      ],
    });
  }

  /**
   * 更新角色
   * @param {string} id - 角色ID
   * @param {Object} roleData - 更新的角色数据
   * @return {Promise<Object>} 更新后的角色
   */
  async update(id, roleData) {
    const { ctx } = this;
    const role = await this.findById(id);
    if (!role) {
      ctx.throw(404, '角色不存在');
    }

    // 检查code是否已存在（排除当前角色）
    if (roleData.code && roleData.code !== role.code) {
      const existingRole = await ctx.model.Role.findOne({
        where: {
          code: roleData.code,
          id: { [ctx.app.Sequelize.Op.ne]: id }
        }
      });
      if (existingRole) {
        ctx.throw(400, '角色编码已存在，请使用其他编码');
      }
    }

    return role.update(roleData);
  }

  /**
   * 删除角色
   * @param {string} id - 角色ID
   * @return {Promise<Boolean>} 是否删除成功
   */
  async destroy(id) {
    const { ctx } = this;
    const role = await this.findById(id);
    if (!role) {
      ctx.throw(404, '角色不存在');
    }

    // 检查是否有用户关联
    const users = await ctx.model.UserRole.count({
      where: { role_code: role.code },
    });

    if (users > 0) {
      ctx.throw(400, '该角色存在关联用户，无法删除');
    }

    return role.destroy();
  }

  /**
   * 更新角色状态
   * @param {string} id - 角色ID
   * @param {boolean} status - 状态
   * @return {Promise<Object>} 更新后的角色
   */
  async updateStatus(id, status) {
    const { ctx } = this;
    const role = await this.findById(id);
    if (!role) {
      ctx.throw(404, '角色不存在');
    }

    role.status = status;
    return role.save();
  }

  /**
   * 为用户分配角色
   * @param {string} userId - 用户ID
   * @param {Array} roleCodes - 角色编码数组
   * @return {Promise<Boolean>} 是否分配成功
   */
  async assignRoles(userId, roleCodes) {
    const { ctx } = this;
    // 先删除用户原有角色
    await ctx.model.UserRole.destroy({
      where: { user_id: userId },
    });

    // 过滤掉无效的角色编码（null、undefined、空字符串）
    const validRoleCodes = roleCodes.filter(roleCode => roleCode && roleCode.trim() !== '');

    // 添加新角色
    const userRoles = validRoleCodes.map(roleCode => ({
      id: generateSnowflakeId(),
      user_id: userId,
      role_code: roleCode,
    }));

    await ctx.model.UserRole.bulkCreate(userRoles);
    return true;
  }

  /**
   * 获取用户的角色列表
   * @param {string} userId - 用户ID
   * @return {Promise<Array>} 角色列表
   */
  async getUserRoles(userId) {
    const { ctx } = this;
    const userRoles = await ctx.model.UserRole.findAll({
      where: { user_id: userId },
      include: [
        { model: ctx.model.Role, as: 'role', attributes: ['id', 'name', 'code'] },
      ],
    });

    return userRoles.map(item => ({
      id: item.role.id,
      name: item.role.name,
      code: item.role.code,
    }));
  }

  /**
   * 批量删除角色
   * @param {Array} ids - 角色ID数组
   * @return {Promise<Boolean>} 是否删除成功
   */
  async batchDestroy(ids) {
    const { ctx } = this;

    // 检查是否有用户关联
    const userRoles = await ctx.model.UserRole.findAll({
      where: { role_code: ids },
      attributes: ['role_code'],
      group: ['role_code'],
    });

    const usedRoleIds = userRoles.map(item => item.role_code);
    const availableRoleIds = ids.filter(id => !usedRoleIds.includes(id));

    if (availableRoleIds.length === 0) {
      ctx.throw(400, '所有角色都存在关联用户，无法删除');
    }

    // 批量删除可用的角色
    const result = await ctx.model.Role.destroy({
      where: { id: availableRoleIds },
    });

    return result > 0;
  }

  /**
   * 获取所有角色（不分页）
   * @param {Object} query - 查询条件
   * @return {Promise<Array>} 角色列表
   */
  async getAllRoles(query = {}) {
    const { ctx } = this;
    const where = {};

    if (query.name) {
      where.name = { [ctx.Sequelize.Op.like]: `%${query.name}%` };
    }

    if (query.status !== undefined && query.status !== '') {
      where.status = query.status;
    }

    return ctx.model.Role.findAll({
      where,
      order: [['create_time', 'DESC']],
    });
  }
}

module.exports = RoleService;
